﻿namespace Stee.GIS.LocationSearch.Interfaces.Utilities
{
    using System;
    using System.Text;
    using System.Text.RegularExpressions;

    public class QueryInputModel
    {
        #region Patterns
        //(=(?<_searchQualifierPart>\w{1,3}\s*)|)
        /*
         * |表示可有可无
         * \s表示包含空格（我们在前面会取消多余的空格 ，把多个变成最多一个）
         */
        private static readonly string SearchQualifierPart = @"((=(?<" + nameof(SearchQualifierPart) + @">[a-zA-Z]{1,3}\s))|)";//add=
        private static readonly string ShortCodePart = @"((?<" + nameof(ShortCodePart) + @">\\[a-zA-Z]{2}\s)|)";
        private static readonly string SearchTextPart = @"(?<" + nameof(SearchTextPart) + @">[\u4e00-\u9fa5_a-zA-Z0-9\s\,]+)";
        private static readonly string StationCodePart = @"(?<StationCodePart>\,[a-zA-Z0-9\s]{1,10}(?!.*(\,[a-zA-Z0-9\s]{1,10})))";
        //private static readonly string StationCodePart = $@"((\,[a-zA-Z0-9]{1,10})(?!.*(\,?<"+ nameof(StationCodePart) +">[a-zA-Z0-9]{1,10})))";
        private static readonly string FreeTextPart = @"(\;(?<" + nameof(FreeTextPart) + @">\s*\w{1,20}\s*)|)";

        public static readonly string FullPattern =
            $@"^{SearchQualifierPart}{ShortCodePart}{SearchTextPart}{StationCodePart}{FreeTextPart}$";
        private static readonly string NotContainsStationCode =
            $@"^{SearchQualifierPart}{ShortCodePart}{SearchTextPart}{FreeTextPart}$";
        #endregion
        /// <summary>
        /// such as：\HA
        /// </summary>
        public string ShortCode { get; set; }

        public bool IsHaveShortCode => !string.IsNullOrWhiteSpace(this.ShortCode);

        /// <summary>
        /// such as：OP
        /// </summary>
        public string SearchQualifier { get; set; }

        public bool IsHaveSearchQualifier => !string.IsNullOrWhiteSpace(this.SearchQualifier);

        public string SearchText { get; set; }

        public string StationCode { get; set; }
        public string FreeText { get; set; }
        private SearchInputType PatternType { get; set; }

        public static string CheckNullOrEmpty(string searchInputText)
        {

            searchInputText = searchInputText.Trim();
            searchInputText = Regex.Replace(searchInputText, @"\s\s+", " ");
            return searchInputText;

        }

        public bool TryParse(string searchInputText, out Match matchResult)
        {
            CheckNullOrEmpty(searchInputText);
            var canParsed = false;
            if (Regex.IsMatch(searchInputText, FullPattern))
            {
                canParsed = true;
                this.PatternType = SearchInputType.Full;
                matchResult = Regex.Match(searchInputText, FullPattern);
            }
            else if (Regex.IsMatch(searchInputText, NotContainsStationCode))
            {

                canParsed = true;
                this.PatternType = SearchInputType.NoStationCode;
                matchResult = Regex.Match(searchInputText, NotContainsStationCode);
            }
            else
            {
                this.PatternType = SearchInputType.None;
                matchResult = null;
            }

            return canParsed;


        }

        private static System.Text.RegularExpressions.Match Match(string input, SearchInputType pattern) =>
            pattern switch
            {
                SearchInputType.NoStationCode => Regex.Match(input, NotContainsStationCode),
                SearchInputType.Full => Regex.Match(input, FullPattern),
                _ => throw new ArgumentOutOfRangeException(nameof(pattern), pattern, null)
            };

        public QueryInputModel(string searchInputText) => this.Create(searchInputText);

        private void Create(string searchInputText)
        {

            //检查并去掉空格
            searchInputText = CheckNullOrEmpty(searchInputText);
            if (!this.TryParse(searchInputText, out var matchResult))
            {
                var unKnownPatternException = new ArgumentException($"{searchInputText} has unKnownPattern");
                Console.WriteLine(unKnownPatternException.Message);
                this.SearchText = searchInputText;
                return;
            }

            /*改成Getter*/
            this.SearchQualifier = matchResult.Groups.ContainsKey(nameof(SearchQualifierPart))
                ? matchResult.Groups[nameof(SearchQualifierPart)].Value.Trim() : null;
            this.ShortCode = matchResult.Groups.ContainsKey(nameof(ShortCodePart))
                ? matchResult.Groups[nameof(ShortCodePart)].Value.Trim('\\').Trim() : null;
            this.SearchText = matchResult.Groups.ContainsKey(nameof(SearchTextPart))
                ? matchResult.Groups[nameof(SearchTextPart)].Value.Trim() : null;
            this.StationCode = matchResult.Groups.ContainsKey(nameof(StationCodePart))
                ? matchResult.Groups[nameof(StationCodePart)].Value.Trim(',').Trim() : null;
            this.FreeText = matchResult.Groups.ContainsKey(nameof(FreeTextPart))
                ? matchResult.Groups[nameof(FreeTextPart)].Value.Trim() : null;


        }


        public override string ToString()
        {
            const string nullText = "null";
            var sb = new StringBuilder();
            _ = sb.Append($"{nameof(this.PatternType)}={Enum.GetName(this.PatternType.GetType(), this.PatternType)}    ");
            _ = sb.Append($"{nameof(this.SearchQualifier)}={this.SearchQualifier ?? nullText}   ");
            _ = sb.Append($"{nameof(this.ShortCode)}={this.ShortCode ?? nullText}   ");
            _ = sb.Append($"{nameof(this.SearchText)}={this.SearchText ?? nullText}   ");
            _ = sb.Append($"{nameof(this.StationCode)}={this.StationCode ?? nullText}   ");
            _ = sb.Append($"{nameof(this.FreeText)}={this.FreeText ?? nullText}   ");
            return sb.ToString();
        }

    }


}
